﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;

namespace ModelViewer
{
    public class NumericSpinner : NumericUpDown
    {
        private bool captured = false;
        private Cursor spinCursor = null;

        /// <summary>
        /// A cursor to use when we are spinning
        /// </summary>
        [Browsable(true)]
        [Category("Appearance")]
        public Cursor SpinCursor
        {
            get { return spinCursor; }
            set { spinCursor = value; }
        }

        private Point lastMouse = new Point(0, 0);

        private Cursor savedCursor = null;

        protected override void OnMouseDown(MouseEventArgs e)
        {
            lastMouse = e.Location;

            base.OnMouseDown(e);

            captured = true;
            Capture = true;
            if (spinCursor != null)
            {
                savedCursor = this.Cursor;
                this.Cursor = spinCursor;
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (captured)
            {
                decimal newValue = this.Value - (decimal)(e.Location.Y - lastMouse.Y) * this.Increment;
                if (newValue > this.Maximum)
                    newValue = this.Maximum;
                else if (newValue < this.Minimum)
                    newValue = this.Minimum;

                this.Value = newValue;
            }

            lastMouse = e.Location;
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);

            captured = false;
            Capture = false;

            if (savedCursor != null)
            {
                this.Cursor = savedCursor;
                savedCursor = null;
            }
        }

        /// <summary>
        /// Each time we change the value, change the steps to something more interesting
        /// </summary>
        /// <param name="e"></param>
        protected override void OnValueChanged(EventArgs e)
        {
            base.OnValueChanged(e);

            decimal newInc = Math.Abs(this.Value / 100);
            decimal minInc = (decimal)Math.Pow(10, -this.DecimalPlaces);
            if (newInc < minInc)
            {
                newInc = minInc;
            }

            this.Increment = newInc;
        }
    }
}
